package com.chess.chessplay.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.chess.chessplay.pojo.Chess;
import com.chess.chessplay.pojo.Onlineplayer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.thymeleaf.expression.Maps;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Component
@ServerEndpoint("/websocket2/{username}")
public class WebSocket2 {
    //日志信息
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * 在线人数
     */
    public static int onlineNumber = 0;
    /**
     * 以用户的姓名为key，WebSocket为对象保存起来
     */

    private static Map<Integer, Chess> chessMap = new ConcurrentHashMap<>();

    private Onlineplayer onlineplayer = new Onlineplayer();
    //棋局数
    private static int chessnum = 0;
    /**
     * 用户名称
     */
    private String username;

    //棋局号
    private int cn;

    //棋手号
    int playernum;

    private String[][] chessbord = new String[21][21];
    /**
     * 建立连接
     *
     * @param session
     * @PathParam("username") String username,
     */
    @OnOpen
    public void onOpen(@PathParam("username") String username, Session session)
    {
        onlineNumber++;
        logger.info("现在来连接的客户id："+session.getId()+"用户名："+username);
        onlineplayer.setSession(session);
        onlineplayer.setUsername(username);
        this.username = username;
        logger.info("有新连接加入！ 当前在线人数" + onlineNumber);
        try {
            Integer n = 0;
            if(chessMap.get(chessnum)!= null){
                n = chessMap.get(chessnum).getNum();
            }

            if(n == 0){
                Chess c1 = new Chess();
                c1.setNum(1);

                c1.setChessnum(chessnum);
                cn = chessnum;
                Onlineplayer o = new Onlineplayer();
                o.setUsername(username);
                o.setSession(session);
                Map<Integer,Onlineplayer> m = new ConcurrentHashMap<>();
                m.put(n,o);
                c1.setData(m);

                c1.setNowplayer(0);

                chessMap.put(chessnum,c1);
            } else if(n < 4 && n > 0){
                Chess c2 = chessMap.get(chessnum);
                c2.setNum(n+1);

                c2.setChessnum(chessnum);
                cn = chessnum;
                Onlineplayer o = new Onlineplayer();
                o.setUsername(username);
                o.setSession(session);
                Map<Integer,Onlineplayer> m = chessMap.get(chessnum).getData();
                m.put(n,o);
                c2.setData(m);

                c2.setNowplayer(0);

                chessMap.put(chessnum,c2);
            }else{
                chessnum++;
                Chess c3 = new Chess();
                c3.setNum(1);

                c3.setChessnum(chessnum);
                cn = chessnum;
                Onlineplayer o = new Onlineplayer();
                o.setUsername(username);
                o.setSession(session);
                Map<Integer,Onlineplayer> m = new ConcurrentHashMap<>();
                m.put(0,o);
                c3.setData(m);

                c3.setNowplayer(0);

                chessMap.put(chessnum,c3);
            }

            //messageType 1代表上线 2代表下线 3不再下棋 4代表普通消息 5 表示其他棋手上线

            Map<String,Object> map2 = new HashMap<String,Object>();
            map2.put("messageType",5);
            map2.put("num",chessMap.get(chessnum).getNum());
            sendMessagechessAll(JSON.toJSONString(map2));

            Map<String,Object> map1 = new HashMap<String,Object>();
            map1.put("messageType",1);
            map1.put("username",username);
            map1.put("cn",cn);
            logger.info("棋局号"+cn);
            playernum = chessMap.get(cn).getNum() - 1;
            logger.info("棋手号"+playernum);
            map1.put("playernum",playernum);
            map1.put("nowplayer",chessMap.get(cn).getNowplayer());
//            map1.put("player",chessMap.get(cn).getPlayer());
            sendMessageTo(JSON.toJSONString(map1),username);


            //把自己的信息加入到map当中去


//            //给自己发一条消息：告诉自己现在都有谁在线
//            Map<String,Object> map2 = new HashMap<String,Object>();
//            map2.put("messageType",3);
//            //移除掉自己
//            Set<String> set = clients.keySet();
//            map2.put("onlineUsers",set);
//            sendMessageTo(JSON.toJSONString(map2),username);
        }
        catch (IOException e){
            logger.info(username+"上线的时候通知所有人发生了错误");
        }

    }

    @OnError
    public void onError(Session session, Throwable error) {
        logger.info("服务端发生了错误"+error.getMessage());
        //error.printStackTrace();
    }
    /**
     * 连接关闭
     */
    @OnClose
    public void onClose()
    {
        onlineNumber--;

        //webSockets.remove(this);
//        Chess c = chessMap.get(cn);
//        int num = c.getNum();
//        num--;
//        c.setNum(num);
//        Map<Integer, Onlineplayer> data = c.getData();
//        data.remove(playernum);
//        c.setData(data);
//        chessMap.put(cn,c);
        try {
            //messageType 1代表上线 2代表下线 3代表在线名单  4代表普通消息

            chessnum%=1000;
            if(chessMap.containsKey(cn)){
                Map<String,Object> map1 = new HashMap<String,Object>();
                map1.put("messageType",2);
                map1.put("username",username);
                sendMessagechessOther(JSON.toJSONString(map1),username);
                chessMap.remove(cn);
            }

        }
        catch (IOException e){
            logger.info(username+"下线的时候通知所有人发生了错误");
        }
        logger.info("有连接关闭！ 当前在线人数" + onlineNumber);
    }

    /**
     * 收到客户端的消息
     *
     * @param message 消息
     * @param session 会话
     */
    @OnMessage
    public void onMessage(String message, Session session)
    {
        try {
            logger.info("来自客户端消息：" + message+"客户端的id是："+session.getId());
            JSONObject jsonObject = JSON.parseObject(message);
            String cn1 = jsonObject.getString(("chessnum"));
            cn = Integer.parseInt(cn1);
            String fromusername = jsonObject.getString("username");
            String cb = jsonObject.getString("chessBoard");
            Integer abandon = jsonObject.getInteger("abandon");
            chessbord = reduction(cb);
            //将数组顺时针旋转九十度
//            chessbord = rotate(chessbord);
//            Chess c = chessMap.get(cn);
//            c.setChess(chessbord);
//            chessMap.put(cn,c);
            Map<String,Object> map = new HashMap<String,Object>();
            if(abandon == 4){
                map.put("messageType",3);

                map.put("chessBoard",convent(chessbord));

                int[] num = calculate(chessbord);
                map.put("red",num[0]);
                map.put("yellow",num[1]);
                map.put("blue",num[2]);
                map.put("green",num[3]);
                map.put("win",winner(num));
            }else {
                map.put("messageType",4);

                map.put("abandon",abandon);
                map.put("num",chessMap.get(cn).getNum());
                map.put("chessBoard",convent(chessbord));
                int player = chessMap.get(cn).getNowplayer();
                player++;
                player %= 4;
                map.put("nowplayer",player);
                chessMap.get(cn).setNowplayer(player);
            }

            sendMessagechessAll(JSON.toJSONString(map));
        }
        catch (Exception e){
            logger.info("发生了错误了");
        }

    }

    private String winner(int[] num){
        int max = num[0];
        int win = 0;
        for(int i = 1; i < num.length; i++){
            if(num[i] > max){
                max = num[i];
                win = i;
            }
        }
        return chessMap.get(cn).getData().get(win).getUsername();
    }

    private int[] calculate(String[][] a){
        int[] num = {0, 0, 0, 0};
        for(int i = 0; i < a.length;i++){
            for(int j = 0; j < a[i].length;j++){
                if(a[i][j].equals("r1")){
                    num[0]++;
                }else if (a[i][j].equals("y1")){
                    num[1]++;
                }else if (a[i][j].equals("b1")){
                    num[2]++;
                }else if (a[i][j].equals("g1")){
                    num[3]++;
                }
            }
        }
        return num;
    }

    private int[][] rotate(int[][] a){
        int n = a.length;
        for(int i = 0; i < n;i++){
            for (int j = 0; j < i;j++){
                int temp = a[i][j];
                a[i][j] = a[j][i];
                a[j][i] = temp;
            }
        }

        for(int i = 0; i < n; i++){
            for(int j = n - 1; j >= n/2 ; j--){
                int temp = a[i][j];
                a[i][j] = a[i][n - j - 1];
                a[i][n - j - 1] = temp;
            }
        }
        return a;
    }


    //还原
    private String[][] reduction(String cb) {
        String[][] chessbord1 = new String[21][21];
        String[] a = cb.split("#");
        for(int l = 0; l < a.length; l++){
            String[] split = a[l].split(",");
            logger.info(a[l]);

            for(int i = 0; i < split.length; i++){
                chessbord1[l][i] = split[i];
//                    logger.info(String.valueOf(chessbord[l][i]));
            }

        }
        return chessbord1;
    }

    private String convent(String[][] a){
        String x = "";
        for(int i = 0; i < a.length; i++){
            if(i != 0){
                x+="#";
            }
            for(int j = 0; j < a[i].length;j++){
                if(j != 0){
                    x+=",";
                }
                x += a[i][j];
            }

        }
        return x;
    }

    public void sendMessagechessAll(String message) throws IOException {
        for(Onlineplayer item : chessMap.get(cn).getData().values()){
            item.getSession().getAsyncRemote().sendText(message);
        }
    }

    public void sendMessagechessOther(String message,String username) throws IOException {
        for(Onlineplayer item : chessMap.get(cn).getData().values()){
            if (!item.getUsername().equals(username)) {
                item.getSession().getAsyncRemote().sendText(message);
            }
        }
    }


    public void sendMessageTo(String message, String ToUserName) throws IOException {

        for (Onlineplayer item : chessMap.get(cn).getData().values()) {
            if (item.getUsername().equals(ToUserName) ) {
                item.getSession().getAsyncRemote().sendText(message);
                break;
            }
        }
    }
//
//    public void sendMessageAll(String message,String FromUserName) throws IOException {
//        for (Onlineplayer item : clients.values()) {
//            item.getSession().getAsyncRemote().sendText(message);
//        }
//    }

    public static synchronized int getOnlineCount() {
        return onlineNumber;
    }

}
